/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * $Id$
 * Universidad de los Andes (Bogota - Colombia)
 * Departamento de Ingenieria de Sistemas y Computacion 
 * Licenciado bajo el esquema Academic Free License version 2.1 
 *
 * Proyecto Cupi2 (http://cupi2.uniandes.edu.co)
 * Ejercicio: n16_tweetSpy
 * Autor: David Mesa & Emil Namen - 22-abr-2013
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */

package uniandes.cupi2.tweetSpy.mundo;

import java.io.File;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;

import twitter4j.Paging;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.User;
import twitter4j.auth.AccessToken;
import uniandes.cupi2.tweetSpy.twitter.ExceptionTwitter;
import uniandes.cupi2.tweetSpy.twitter.LoginTwitter;
import ArbolTrie.Trie;



/**
 *  
 */
public class TweetSpy implements Serializable{


	// -----------------------------------------------------------------
	// Constantes
	// -----------------------------------------------------------------
	private static TweetSpy instancia = null;

	private String UbicacionSerializadoMundo = "/tweetSpy.spy";

	private static final long serialVersionUID = 1L;

	// -----------------------------------------------------------------
	// Atributos
	// -----------------------------------------------------------------

	public Trie < UsuarioBase > usuariosBase;

	public UsuarioBase usuarioBase;

	public Twitter twitter;

	// -----------------------------------------------------------------
	// Constructores
	// -----------------------------------------------------------------

	/** 
	 *  
	 */
	private TweetSpy() {

		File archivo = new File( UbicacionSerializadoMundo );
		usuariosBase = new Trie< UsuarioBase >( );
		twitter = new TwitterFactory().getInstance();
		twitter.setOAuthConsumer(LoginTwitter.CONSUMER_KEY, LoginTwitter.CONSUMER_SECRET);
	}

	// -----------------------------------------------------------------
	// Metodos
	// -----------------------------------------------------------------

	/**
	 * Crea un nuevo ususuariosBase, el cual fue logeado por primera vez. Agrega
	 * el usuario al arbol de logeo.
	 * @param accessToken El token con el cual se va a logear en el futuro.
	 * @param usuario Clase User del usuario a crear.
	 * @param screemName Nombre del usuario.
	 * @param urlFoto Foto del usuario.
	 */
	public void crearUsuario(AccessToken accessToken, User usuario, String screemName, String urlFoto, String clave ) {
		twitter.setOAuthAccessToken( accessToken );
		usuarioBase = new UsuarioBase(accessToken, usuario, screemName, urlFoto, clave);
		try {
			usuariosBase.agregar(screemName, usuarioBase);
		} catch (Exception e) {
			// No tiene screemname
			e.printStackTrace();
		}
	}

	/**
	 * Inicia secion con un usuario ya existente.
	 * @param screemName El nombre de usuario con el cual se va a iniciar secion.
	 * @param clave La clave del usuario.
	 * @throws Exception Manda exception por varias razones.
	 */
	public void iniciarSecion ( String screemName, String clave ) throws Exception
	{
		Iterator< UsuarioBase > iter = usuariosBase.buscar( screemName );
		UsuarioBase actual;
		if ( iter.hasNext( ) )
		{
			actual = iter.next( );
		}
		else 
		{
			throw new Exception( "No se encontro usuario" );
		}
		if ( iter.hasNext( ) )
		{
			throw new Exception( "Encontro mas ususarios con este nombre" );
		}
		if ( actual.iniciarSesion( clave ) )
		{
			usuarioBase = actual;
		}
		else 
		{
			throw new Exception( "La calve no es correcta" );
		}

	}

	/**
	 * Construye y devuelve un iterador con los amigos.
	 * @return Iterador con los amigos.
	 */
	public Iterator<Usuario> darAmigos()
	{
		return usuarioBase.darAmigos();
	}

	/**
	 * Devuelve un iterador con los seguidores del usuario base.
	 * @return Retorna un iterador de ususarios.
	 */
	public Iterator<Usuario> darSeguidores( )
	{
		return usuarioBase.darSeguidores( );
	}

	/**
	 * Retorna un iterador con el indice buscado.
	 * 
	 * @param palabra
	 *            El indice el cual se desea buscar.
	 * @return Iterador con los elementos buscados.
	 */
	public Iterator<Tweet> darIndice(String palabra) {
		return usuarioBase.darIndice(palabra);
	}

	/**
	 * Dar instancia de la clase.
	 * 
	 * @return Retorna el objeto (this).
	 */
	public static TweetSpy getInstance() {
		if (instancia == null) {
			instancia = new TweetSpy();
		}
		return instancia;
	}

	public String darUrlFotoUB( ) {
		return usuarioBase.darUrlFoto();
	}

	public String darScreemNameUB ( )
	{
		return usuarioBase.darScreemName( );
	}

	public Iterator< String > darIndices ( )
	{
		return usuarioBase.darIndices( );
	}

	public Iterator< Tweet > crearIndice ( String indice ) throws ExceptionTwitter
	{
		return usuarioBase.crearIndice(indice);
	}

	public int [] generarFranjas ( ) throws TwitterException
	{
		int [] franjas = new int[4];
		//First param of Paging() is the page number, second is the number per page (this is capped around 200 I think.
		Paging paging = new Paging(1, 40);
		List<Status> statuses = twitter.getUserTimeline(usuarioBase.darScreemName(),paging);
		Iterator<Status> iter = statuses.iterator();
		while( iter.hasNext( ) ) 
		{
			Status actual = iter.next();
			int horas = actual.getCreatedAt().getHours();
			if (horas>0 && horas<5)
			{
				franjas[0]++;
			}
			else if ( horas<12 ) 
			{
				franjas[1]++;
			}
			else if ( horas < 19)
			{
				franjas[2]++;
			}
			else 
			{
				franjas[3]++;
			}
		}
		return franjas;
	}
	
	public Iterator<Usuario>[] darAmigosOSeguidores ( String prefijo )
	{
		return usuarioBase.buscarAmigos(prefijo);
	}
	
	public Iterator<Tweet> consultarIndicesPorPrefijo(String nPrefijo)
	{
		return usuarioBase.consultarIndicesPorPrefijo(nPrefijo);
	}

}